//
//  PPNetworkHelper.m
//  JiFengDaRen
//
//  Created by 陈如意 on 2018/3/16.
//  Copyright © 2018年 陈永发. All rights reserved.
//

#import "PPNetworkHelper.h"
#import "AFNetworking.h"
#import "AFNetworkActivityIndicatorManager.h"

#ifdef DEBUG
#define PPLog(...) printf("[%s] %s [第%d行]: %s\n", __TIME__ ,__PRETTY_FUNCTION__ ,__LINE__, [[NSString stringWithFormat:__VA_ARGS__] UTF8String])
#else
#define PPLog(...)
#endif

#define NSStringFormat(format,...) [NSString stringWithFormat:format,##__VA_ARGS__]


@implementation PPNetworkHelper

static BOOL _isOpenLog;   // 是否已开启日志打印
static NSMutableArray *_allSessionTask;
static AFHTTPSessionManager *_sessionManager;

+ (void)openLog {
    _isOpenLog = YES;
}

+ (void)closeLog {
    _isOpenLog = NO;
}

+ (void)cancelAllRequest {
    // 锁操作
    @synchronized(self) {
        [[self allSessionTask] enumerateObjectsUsingBlock:^(NSURLSessionTask  *_Nonnull task, NSUInteger idx, BOOL * _Nonnull stop) {
            [task cancel];
        }];
        [[self allSessionTask] removeAllObjects];
    }
}

+ (void)cancelRequestWithURL:(NSString *)URL {
    if (!URL) { return; }
    @synchronized (self) {
        [[self allSessionTask] enumerateObjectsUsingBlock:^(NSURLSessionTask  *_Nonnull task, NSUInteger idx, BOOL * _Nonnull stop) {
            if ([task.currentRequest.URL.absoluteString hasPrefix:URL]) {
                [task cancel];
                [[self allSessionTask] removeObject:task];
                *stop = YES;
            }
        }];
    }
}


#pragma mark - GET请求是否自动缓存
+ (NSURLSessionTask *)GET:(NSString *)URL
               parameters:(id)parameters
                    cache:(BOOL)cache
                  encrypt:(BOOL)encrypt
                   decode:(BOOL)decode
            responseCache:(PPHttpRequestCache)responseCache
                  success:(PPHttpRequestSuccess)success
                  failure:(PPHttpRequestFailed)failure {
    
    URL = [NSString stringWithFormat:@"%@%@",BASE_URL,URL];

    if (cache == YES) {
        //读取缓存
        responseCache!=nil ? responseCache([PPNetworkCache httpCacheForURL:URL parameters:parameters]) : nil;
//        if (responseCache != nil) {
//            // 解密
//            [self decodeWithResponseObject:responseCache decode:YES complection:^(id result) {
//                responseCache(result);
//            }];
//        }
    }

    parameters = [self cryptWithParameters:parameters encrypt:encrypt];
    
    NSURLSessionTask *sessionTask = [_sessionManager GET:URL parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        if (_isOpenLog) {PPLog(@"responseObject = %@",responseObject);}
        
        [[self allSessionTask] removeObject:task];
        
        // 解密
        [self decodeWithResponseObject:responseObject decode:decode complection:^(id result) {
            success ? success(result) : nil;
            //对数据进行异步缓存
            if (cache == YES) {
                responseCache!=nil ? [PPNetworkCache setHttpCache:result URL:URL parameters:parameters] : nil;
            }
        }];
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        if (_isOpenLog) {PPLog(@"error = %@",error);}
        [[self allSessionTask] removeObject:task];
        failure ? failure(error) : nil;
        
    }];
    // 添加sessionTask到数组
    sessionTask ? [[self allSessionTask] addObject:sessionTask] : nil ;
    
    return sessionTask;
}

#pragma mark - POST请求是否自动缓存
+ (NSURLSessionTask *)POST:(NSString *)URL
                parameters:(id)parameters
                     cache:(BOOL)cache
                   encrypt:(BOOL)encrypt
                    decode:(BOOL)decode
             responseCache:(PPHttpRequestCache)responseCache
                   success:(PPHttpRequestSuccess)success
                   failure:(PPHttpRequestFailed)failure {
    
    URL = [NSString stringWithFormat:@"%@%@",BASE_URL,URL];

    if (cache == YES) {
        //读取缓存
        responseCache!=nil ? responseCache([PPNetworkCache httpCacheForURL:URL parameters:parameters]) : nil;
//        if (responseCache != nil) {
//            [self decodeWithResponseObject:responseCache decode:decode complection:^(id result) {
//                responseCache(result);
//            }];
//        }
    }
    parameters = [self cryptWithParameters:parameters encrypt:encrypt];
    
    NSURLSessionTask *sessionTask = [_sessionManager POST:URL parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
        
    } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
        
        if (_isOpenLog) {PPLog(@"responseObject = %@",responseObject);}
        [[self allSessionTask] removeObject:task];
        
        // 解密
        [self decodeWithResponseObject:responseObject decode:decode complection:^(id result) {
            success ? success(result) : nil;
            //对数据进行异步缓存
            if (cache == YES) {
                responseCache!=nil ? [PPNetworkCache setHttpCache:result URL:URL parameters:parameters] : nil;
            }
        }];
        
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
        
        if (_isOpenLog) {PPLog(@"error = %@",error);}
        [[self allSessionTask] removeObject:task];
        failure ? failure(error) : nil;
        
    }];
    
    // 添加最新的sessionTask到数组
    sessionTask ? [[self allSessionTask] addObject:sessionTask] : nil ;
    return sessionTask;
}


/**
 存储着所有的请求task数组
 */
+ (NSMutableArray *)allSessionTask {
    if (!_allSessionTask) {
        _allSessionTask = [[NSMutableArray alloc] init];
    }
    return _allSessionTask;
}

#pragma mark - 初始化AFHTTPSessionManager相关属性

/**
 *  所有的HTTP请求共享一个AFHTTPSessionManager
 *  原理参考地址:http://www.jianshu.com/p/5969bbb4af9f
 */
+ (void)initialize {
    _sessionManager = [AFHTTPSessionManager manager];
    _sessionManager.requestSerializer.timeoutInterval = 30.f;
    _sessionManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/html", @"text/json", @"text/plain", @"text/javascript", @"text/xml", @"image/*", nil];
    // 打开状态栏的等待菊花
    [AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
}

#pragma mark - 重置AFHTTPSessionManager相关属性

+ (void)setAFHTTPSessionManagerProperty:(void (^)(AFHTTPSessionManager *))sessionManager {
    sessionManager ? sessionManager(_sessionManager) : nil;
}

+ (void)setRequestSerializer:(PPRequestSerializer)requestSerializer {
    _sessionManager.requestSerializer = requestSerializer==PPRequestSerializerHTTP ? [AFHTTPRequestSerializer serializer] : [AFJSONRequestSerializer serializer];
}

+ (void)setResponseSerializer:(PPResponseSerializer)responseSerializer {
    _sessionManager.responseSerializer = responseSerializer==PPResponseSerializerHTTP ? [AFHTTPResponseSerializer serializer] : [AFJSONResponseSerializer serializer];
}

+ (void)setRequestTimeoutInterval:(NSTimeInterval)time {
    _sessionManager.requestSerializer.timeoutInterval = time;
}

+ (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field {
    [_sessionManager.requestSerializer setValue:value forHTTPHeaderField:field];
}

+ (void)openNetworkActivityIndicator:(BOOL)open {
    [[AFNetworkActivityIndicatorManager sharedManager] setEnabled:open];
}

+ (void)setSecurityPolicyWithCerPath:(NSString *)cerPath validatesDomainName:(BOOL)validatesDomainName {
    NSData *cerData = [NSData dataWithContentsOfFile:cerPath];
    // 使用证书验证模式
    AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
    // 如果需要验证自建证书(无效证书)，需要设置为YES
    securityPolicy.allowInvalidCertificates = YES;
    // 是否需要验证域名，默认为YES;
    securityPolicy.validatesDomainName = validatesDomainName;
    securityPolicy.pinnedCertificates = [[NSSet alloc] initWithObjects:cerData, nil];
    
    [_sessionManager setSecurityPolicy:securityPolicy];
}

#pragma mark -- RSA
#pragma mark -- RSA加密body
+ (NSDictionary *)cryptWithParameters:(NSDictionary *)parameters encrypt:(BOOL)isEncrypt{
    NSDictionary *requestBody;
    if (!parameters){
        requestBody = @{};
        return requestBody;
    }else{
        if (isEncrypt) {
            HBRSAHandler* handler = [HBRSAHandler  shareHandler];
            requestBody = [handler encrencryptWithDictionary:parameters];
        }else{
            requestBody = parameters;
        }
    }
    return  requestBody;
    
}

#pragma mark --  RSA解密
+ (void)decodeWithResponseObject:(id)responseObject decode:(BOOL)isDecode complection:(void(^)(id result))successBlock {
    id result = responseObject;
    if (!result) {
        SHLog(@"返回数据JSON解析失败");
    }
    if (!isDecode) {
        successBlock(result);
        return;
    }
    HBRSAHandler* handler = [HBRSAHandler shareHandler];
    if ([result isKindOfClass:[NSDictionary class]] ) {
        BOOL  success = [result[@"success"] boolValue];
        if (success) {
            if (![result[@"data"] isKindOfClass:[NSDictionary class]]) {
                
                return;
            }
            NSDictionary *data = result[@"data"];
            if ([data objectForKey:@"msg"] &&[data objectForKey:@"signature"] ) {//加密
                
                NSString *msg = result[@"data"][@"msg"];
                if (msg) {
                    msg = [handler decryptWithPrivatecKey:msg];
                }
                
                if (([msg hasPrefix:@"{"] && [msg hasSuffix:@"}"]) || ([msg hasPrefix:@"["] && [msg hasSuffix:@"]"])){
                    
                    NSData *jsonData = [msg dataUsingEncoding:NSUTF8StringEncoding];
                    NSDictionary *msgDict = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableLeaves error:nil];
                    
                    NSMutableDictionary *resultDict = [[NSMutableDictionary alloc]init];
                    [resultDict setValue:result[@"success"] forKey:@"success"];
                    [resultDict setValue:msgDict forKey:@"data"];
                    
                    successBlock(resultDict);
                    
                }else{
                    NSMutableDictionary *resultDict = [[NSMutableDictionary alloc]init];
                    [resultDict setValue:result[@"success"] forKey:@"success"];
                    [resultDict setValue:msg forKey:@"data"];
                    successBlock(resultDict);
                }
                
            }else{
                successBlock(result);
            }
            
        }else{
            
            if ([result[@"data"] isKindOfClass:[NSString class]]) {
                
                if ([result[@"data"] isEqualToString:@"relogin"]) {
                    //强制跳转到登录页面
                }
                successBlock(result);
            }else{
                
                SHLog(@"返回数据格式不对！");
            }
            
        }
    }
    
}

@end


#pragma mark - NSDictionary,NSArray的分类
/*
 ************************************************************************************
 *新建NSDictionary与NSArray的分类, 控制台打印json数据中的中文
 ************************************************************************************
 */

#ifdef DEBUG
@implementation NSArray (PP)

- (NSString *)descriptionWithLocale:(id)locale {
    NSMutableString *strM = [NSMutableString stringWithString:@"(\n"];
    [self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
        [strM appendFormat:@"\t%@,\n", obj];
    }];
    [strM appendString:@")"];
    
    return strM;
}

@end

@implementation NSDictionary (PP)

- (NSString *)descriptionWithLocale:(id)locale {
    NSMutableString *strM = [NSMutableString stringWithString:@"{\n"];
    [self enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {
        [strM appendFormat:@"\t%@ = %@;\n", key, obj];
    }];
    
    [strM appendString:@"}\n"];
    
    return strM;
}
@end
#endif

